package io.xxx.xbutler.web.controller;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hy.corecode.idgen.WFGIdGenerator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.xxx.xbutler.domain.User;
import io.xxx.xbutler.domain.task.Task;
import io.xxx.xbutler.domain.task.TaskItem;
import io.xxx.xbutler.domain.task.TaskStatus;
import io.xxx.xbutler.service.TaskService;
import io.xxx.xbutler.web.controller.form.CreateTaskForm;
import io.xxx.xbutler.web.controller.form.TaskForm;
import io.xxx.xbutler.web.controller.form.TaskItemForm;
import io.xxx.xbutler.web.controller.form.UpdateTaskForm;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.BeanUtils;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Tag(name = "Task", description = "任务APIs")
@Slf4j
@RestController
@RequestMapping("/task")
public class TaskController {

    @Resource
    private WFGIdGenerator idGenerator;

    @Resource
    private TaskService taskService;

    @Operation(summary = "查询任务列表", description = "返回任务列表")
    @GetMapping("/list")
    public Page<Task> list(Task task,
                           @RequestParam(defaultValue = "1") Integer pageNumber,
                           @RequestParam(defaultValue = "20") Integer pageSize) {
        return taskService.list(task, new Page<>(pageNumber, pageSize));
    }

    @GetMapping("/get")
    public Task get(@RequestParam Long id) {
        return taskService.get(id);
    }

    @PostMapping("/create")
    public Long create(@RequestBody @Valid CreateTaskForm form,
                       Errors errors,
                       @RequestHeader("X-User") User user) {
        log.info("创建任务[{}]", JSON.toJSONString(form));
        if (errors.hasErrors()) {
            String message = errors.getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.joining(", "));
            throw new RuntimeException(message);
        }
        long taskId = idGenerator.next();
        LocalDateTime now = LocalDateTime.now();
        Pair<Task, List<TaskItem>> pair = build(form, taskId, now);
        Task task = pair.getLeft();
        task.setCreatedId(user.getId())
                .setCreatedName(user.getName())
                .setCreatedTime(LocalDateTime.now());
        taskService.create(task, pair.getRight(), user);
        return taskId;
    }

    @PutMapping("/update")
    public void update(@RequestBody @Valid UpdateTaskForm form,
                       Errors errors,
                       @RequestHeader("X-User") User user) {
        log.debug("更新任务[{}]", JSON.toJSONString(form));
        if (errors.hasErrors()) {
            String message = errors.getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.joining(", "));
            throw new RuntimeException(message);
        }

        Long taskId = form.getId();
        LocalDateTime now = LocalDateTime.now();
        Pair<Task, List<TaskItem>> pair = build(form, taskId, now);
        Task task = pair.getLeft();
        task.setUpdatedId(user.getId())
                .setUpdatedName(user.getName())
                .setUpdatedTime(LocalDateTime.now());
        taskService.update(task, pair.getRight(), user);
    }

    private Pair<Task, List<TaskItem>> build(TaskForm form, Long taskId, LocalDateTime now) {
        form.validate();
        List<List<TaskItemForm>> groupItemForms = form.getItems();

        Task task = new Task();
        BeanUtils.copyProperties(form, task);
        task.setId(taskId);
        task.setStatus(TaskStatus.RUNNABLE);
        task.setBackend(false);
        task.setGroupCount(groupItemForms.size());

        List<List<TaskItem>> groupItems = new ArrayList<>(groupItemForms.size());
        for (int i = 0; i < groupItemForms.size(); i++) {
            List<TaskItemForm> itemForms = groupItemForms.get(i);
            List<TaskItem> items = new ArrayList<>(itemForms.size());
            for (int j = 0; j < itemForms.size(); j++) {
                TaskItemForm itemForm = itemForms.get(j);
                TaskItem item = new TaskItem();
                BeanUtils.copyProperties(itemForm, item);
                item.setId(idGenerator.next());
                item.setTaskId(taskId);
                item.setPsn(i);
                item.setSn(j);
                item.setCreatedTime(now);
                items.add(item);
            }
            groupItems.add(items);
        }

        task.setItems(groupItems);
        List<TaskItem> items = groupItems.stream()
                .flatMap(Collection::stream)
                .toList();

        return Pair.of(task, items);
    }

    @DeleteMapping("/delete")
    public void delete(@RequestParam Long id, @RequestHeader User user) {
        log.debug("删除任务[id:{}, user:{}]", id, JSON.toJSONString(user));
        taskService.delete(id, user);
    }

    @PutMapping("/cancel")
    public void cancel(@RequestParam Long id, @RequestHeader User user) {
        log.debug("取消任务[id:{}, user:{}]", id, JSON.toJSONString(user));
        taskService.cancel(id, user);
    }
}
